﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using log4net;

public partial class Pay : System.Web.UI.Page
{
    protected JObject jsonResponse;

    protected string requestCsrf;

    protected string paymentID;
    protected string paymentState;
    protected string finalAmount;
    protected string currency;
    protected string transactionID;
    protected string payerFirstName;
    protected string payerLastName;
    protected string recipientName;
    protected string addressLine1;
    protected string addressLine2;
    protected string city;
    protected string state;
    protected string postalCode;
    protected string countryCode;
    protected string addressLines;

    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    protected void Page_Load(object sender, EventArgs e)
    {
        log4net.Config.XmlConfigurator.Configure();

        if (Session["csrf"] == null)
        {
            log.Info(
                "Session expired: force redirect back to Index."
            );

            Response.Redirect("Index.aspx");
        }

        // Proceed to Checkout flow
        if (Request.QueryString["paymentId"] != null && Request.QueryString["PayerID"] != null)
        {
            var doPaymentResponse = PayPalMethods.doPayment(Session["accessToken"].ToString(), Request.QueryString["paymentId"], Request.QueryString["PayerID"]);

           int httpStatusCode = doPaymentResponse.Item1;
           jsonResponse = doPaymentResponse.Item2;

           // error
           if (httpStatusCode != 200)
           {
               Session["error"] = jsonResponse;
               Response.Redirect("Error.aspx", true);
           }
        }
        // Express checkout flow
        else
        {
            requestCsrf = (Request.Form["csrf"] != null) ? Request.Form["csrf"].ToString() : "";

            if (requestCsrf == Session["csrf"].ToString())
            {
                // session JSON string converted to ExpressCheckoutPaymentData object
                PayPalObjects.ExpressCheckoutPaymentData deserializedEC = JsonConvert.DeserializeObject<PayPalObjects.ExpressCheckoutPaymentData>(Session["expressCheckoutPaymentData"].ToString());

                // update object fields based on form selections
                deserializedEC.transactions[0].amount.total = (
                    float.Parse(deserializedEC.transactions[0].amount.total) +
                    float.Parse(Request.Form["shipping_method"]) -
                    float.Parse(deserializedEC.transactions[0].amount.details.shipping)
                ).ToString();

                deserializedEC.transactions[0].amount.details.shipping = Request.Form["shipping_method"].ToString();

                string expressCheckoutPaymentUpdateDataJson = JsonConvert.SerializeObject(deserializedEC.transactions[0].amount, Formatting.Indented);

                var doPaymentResponse = PayPalMethods.doPayment(Session["accessToken"].ToString(), Session["paymentId"].ToString(), Session["PayerID"].ToString(), expressCheckoutPaymentUpdateDataJson);

                int httpStatusCode = doPaymentResponse.Item1;
                jsonResponse = doPaymentResponse.Item2;

                // error
                if (httpStatusCode != 200)
                {
                    Session["error"] = jsonResponse;
                    Response.Redirect("Error.aspx", true);
                }
            }
            else
            {
                // tampered data, return to home page
                log.Info(
                    "Csrf Token failed validation: forced redirect back to Index."
                );
            }
        }

        paymentID = jsonResponse["id"].ToString();
        paymentState = jsonResponse["state"].ToString();
        finalAmount = jsonResponse["transactions"][0]["amount"]["total"].ToString();
        currency = jsonResponse["transactions"][0]["amount"]["currency"].ToString();
        transactionID = jsonResponse["transactions"][0]["related_resources"][0]["sale"]["id"].ToString();
        payerFirstName = jsonResponse["payer"]["payer_info"]["first_name"].ToString();
        payerLastName = jsonResponse["payer"]["payer_info"]["last_name"].ToString();
        recipientName = jsonResponse["payer"]["payer_info"]["shipping_address"]["recipient_name"].ToString();
        addressLine1 = jsonResponse["payer"]["payer_info"]["shipping_address"]["line1"].ToString();
        addressLine2 = (jsonResponse["payer"]["payer_info"]["shipping_address"]["line2"] != null) ? jsonResponse["payer"]["payer_info"]["shipping_address"]["line2"].ToString() : "";
        city = jsonResponse["payer"]["payer_info"]["shipping_address"]["city"].ToString();
        state = jsonResponse["payer"]["payer_info"]["shipping_address"]["state"].ToString();
        postalCode = jsonResponse["payer"]["payer_info"]["shipping_address"]["postal_code"].ToString();
        countryCode = jsonResponse["payer"]["payer_info"]["shipping_address"]["country_code"].ToString();

        // format address lines so no blank line
        List<string> addr = new List<string>();

        if (addressLine1 != "")
            addr.Add(addressLine1);
        if (addressLine2 != "")
            addr.Add(addressLine2);

        addressLines = string.Join("<br />", addr);

        log.Info(
            "Payment complete: clearing session."
        );

        Session.Abandon();
    }
}